home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / DB / dbase.php < prev    next >
Encoding:
PHP Script  |  2005-07-07  |  15.4 KB  |  511 lines

  1. <?php
  2.  
  3. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  4.  
  5. /**
  6.  * The PEAR DB driver for PHP's dbase extension
  7.  * for interacting with dBase databases
  8.  *
  9.  * PHP versions 4 and 5
  10.  *
  11.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  12.  * that is available through the world-wide-web at the following URI:
  13.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  14.  * the PHP License and are unable to obtain it through the web, please
  15.  * send a note to license@php.net so we can mail you a copy immediately.
  16.  *
  17.  * @category   Database
  18.  * @package    DB
  19.  * @author     Tomas V.V. Cox <cox@idecnet.com>
  20.  * @author     Daniel Convissor <danielc@php.net>
  21.  * @copyright  1997-2005 The PHP Group
  22.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  23.  * @version    CVS: $Id: dbase.php,v 1.39 2005/02/19 23:25:25 danielc Exp $
  24.  * @link       http://pear.php.net/package/DB
  25.  */
  26.  
  27. /**
  28.  * Obtain the DB_common class so it can be extended from
  29.  */
  30. require_once 'DB/common.php';
  31.  
  32. /**
  33.  * The methods PEAR DB uses to interact with PHP's dbase extension
  34.  * for interacting with dBase databases
  35.  *
  36.  * These methods overload the ones declared in DB_common.
  37.  *
  38.  * @category   Database
  39.  * @package    DB
  40.  * @author     Tomas V.V. Cox <cox@idecnet.com>
  41.  * @author     Daniel Convissor <danielc@php.net>
  42.  * @copyright  1997-2005 The PHP Group
  43.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  44.  * @version    Release: 1.7.6
  45.  * @link       http://pear.php.net/package/DB
  46.  */
  47. class DB_dbase extends DB_common
  48. {
  49.     // {{{ properties
  50.  
  51.     /**
  52.      * The DB driver type (mysql, oci8, odbc, etc.)
  53.      * @var string
  54.      */
  55.     var $phptype = 'dbase';
  56.  
  57.     /**
  58.      * The database syntax variant to be used (db2, access, etc.), if any
  59.      * @var string
  60.      */
  61.     var $dbsyntax = 'dbase';
  62.  
  63.     /**
  64.      * The capabilities of this DB implementation
  65.      *
  66.      * The 'new_link' element contains the PHP version that first provided
  67.      * new_link support for this DBMS.  Contains false if it's unsupported.
  68.      *
  69.      * Meaning of the 'limit' element:
  70.      *   + 'emulate' = emulate with fetch row by number
  71.      *   + 'alter'   = alter the query
  72.      *   + false     = skip rows
  73.      *
  74.      * @var array
  75.      */
  76.     var $features = array(
  77.         'limit'         => false,
  78.         'new_link'      => false,
  79.         'numrows'       => true,
  80.         'pconnect'      => false,
  81.         'prepare'       => false,
  82.         'ssl'           => false,
  83.         'transactions'  => false,
  84.     );
  85.  
  86.     /**
  87.      * A mapping of native error codes to DB error codes
  88.      * @var array
  89.      */
  90.     var $errorcode_map = array(
  91.     );
  92.  
  93.     /**
  94.      * The raw database connection created by PHP
  95.      * @var resource
  96.      */
  97.     var $connection;
  98.  
  99.     /**
  100.      * The DSN information for connecting to a database
  101.      * @var array
  102.      */
  103.     var $dsn = array();
  104.  
  105.  
  106.     /**
  107.      * A means of emulating result resources
  108.      * @var array
  109.      */
  110.     var $res_row = array();
  111.  
  112.     /**
  113.      * The quantity of results so far
  114.      *
  115.      * For emulating result resources.
  116.      *
  117.      * @var integer
  118.      */
  119.     var $result = 0;
  120.  
  121.     /**
  122.      * Maps dbase data type id's to human readable strings
  123.      *
  124.      * The human readable values are based on the output of PHP's
  125.      * dbase_get_header_info() function.
  126.      *
  127.      * @var array
  128.      * @since Property available since Release 1.7.0
  129.      */
  130.     var $types = array(
  131.         'C' => 'character',
  132.         'D' => 'date',
  133.         'L' => 'boolean',
  134.         'M' => 'memo',
  135.         'N' => 'number',
  136.     );
  137.  
  138.  
  139.     // }}}
  140.     // {{{ constructor
  141.  
  142.     /**
  143.      * This constructor calls <kbd>$this->DB_common()</kbd>
  144.      *
  145.      * @return void
  146.      */
  147.     function DB_dbase()
  148.     {
  149.         $this->DB_common();
  150.     }
  151.  
  152.     // }}}
  153.     // {{{ connect()
  154.  
  155.     /**
  156.      * Connect to the database and create it if it doesn't exist
  157.      *
  158.      * Don't call this method directly.  Use DB::connect() instead.
  159.      *
  160.      * PEAR DB's dbase driver supports the following extra DSN options:
  161.      *   + mode    An integer specifying the read/write mode to use
  162.      *              (0 = read only, 1 = write only, 2 = read/write).
  163.      *              Available since PEAR DB 1.7.0.
  164.      *   + fields  An array of arrays that PHP's dbase_create() function needs
  165.      *              to create a new database.  This information is used if the
  166.      *              dBase file specified in the "database" segment of the DSN
  167.      *              does not exist.  For more info, see the PHP manual's
  168.      *              {@link http://php.net/dbase_create dbase_create()} page.
  169.      *              Available since PEAR DB 1.7.0.
  170.      *
  171.      * Example of how to connect and establish a new dBase file if necessary:
  172.      * <code>
  173.      * require_once 'DB.php';
  174.      *
  175.      * $dsn = array(
  176.      *     'phptype'  => 'dbase',
  177.      *     'database' => '/path/and/name/of/dbase/file',
  178.      *     'mode'     => 2,
  179.      *     'fields'   => array(
  180.      *         array('a', 'N', 5, 0),
  181.      *         array('b', 'C', 40),
  182.      *         array('c', 'C', 255),
  183.      *         array('d', 'C', 20),
  184.      *     ),
  185.      * );
  186.      * $options = array(
  187.      *     'debug'       => 2,
  188.      *     'portability' => DB_PORTABILITY_ALL,
  189.      * );
  190.      *
  191.      * $db =& DB::connect($dsn, $options);
  192.      * if (PEAR::isError($db)) {
  193.      *     die($db->getMessage());
  194.      * }
  195.      * </code>
  196.      *
  197.      * @param array $dsn         the data source name
  198.      * @param bool  $persistent  should the connection be persistent?
  199.      *
  200.      * @return int  DB_OK on success. A DB_Error object on failure.
  201.      */
  202.     function connect($dsn, $persistent = false)
  203.     {
  204.         if (!PEAR::loadExtension('dbase')) {
  205.             return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
  206.         }
  207.  
  208.         $this->dsn = $dsn;
  209.         if ($dsn['dbsyntax']) {
  210.             $this->dbsyntax = $dsn['dbsyntax'];
  211.         }
  212.  
  213.         /*
  214.          * Turn track_errors on for entire script since $php_errormsg
  215.          * is the only way to find errors from the dbase extension.
  216.          */
  217.         ini_set('track_errors', 1);
  218.         $php_errormsg = '';
  219.  
  220.         if (!file_exists($dsn['database'])) {
  221.             $this->dsn['mode'] = 2;
  222.             if (empty($dsn['fields']) || !is_array($dsn['fields'])) {
  223.                 return $this->raiseError(DB_ERROR_CONNECT_FAILED,
  224.                                          null, null, null,
  225.                                          'the dbase file does not exist and '
  226.                                          . 'it could not be created because '
  227.                                          . 'the "fields" element of the DSN '
  228.                                          . 'is not properly set');
  229.             }
  230.             $this->connection = @dbase_create($dsn['database'],
  231.                                               $dsn['fields']);
  232.             if (!$this->connection) {
  233.                 return $this->raiseError(DB_ERROR_CONNECT_FAILED,
  234.                                          null, null, null,
  235.                                          'the dbase file does not exist and '
  236.                                          . 'the attempt to create it failed: '
  237.                                          . $php_errormsg);
  238.             }
  239.         } else {
  240.             if (!isset($this->dsn['mode'])) {
  241.                 $this->dsn['mode'] = 0;
  242.             }
  243.             $this->connection = @dbase_open($dsn['database'],
  244.                                             $this->dsn['mode']);
  245.             if (!$this->connection) {
  246.                 return $this->raiseError(DB_ERROR_CONNECT_FAILED,
  247.                                          null, null, null,
  248.                                          $php_errormsg);
  249.             }
  250.         }
  251.         return DB_OK;
  252.     }
  253.  
  254.     // }}}
  255.     // {{{ disconnect()
  256.  
  257.     /**
  258.      * Disconnects from the database server
  259.      *
  260.      * @return bool  TRUE on success, FALSE on failure
  261.      */
  262.     function disconnect()
  263.     {
  264.         $ret = @dbase_close($this->connection);
  265.         $this->connection = null;
  266.         return $ret;
  267.     }
  268.  
  269.     // }}}
  270.     // {{{ &query()
  271.  
  272.     function &query($query = null)
  273.     {
  274.         // emulate result resources
  275.         $this->res_row[(int)$this->result] = 0;
  276.         $tmp =& new DB_result($this, $this->result++);
  277.         return $tmp;
  278.     }
  279.  
  280.     // }}}
  281.     // {{{ fetchInto()
  282.  
  283.     /**
  284.      * Places a row from the result set into the given array
  285.      *
  286.      * Formating of the array and the data therein are configurable.
  287.      * See DB_result::fetchInto() for more information.
  288.      *
  289.      * This method is not meant to be called directly.  Use
  290.      * DB_result::fetchInto() instead.  It can't be declared "protected"
  291.      * because DB_result is a separate object.
  292.      *
  293.      * @param resource $result    the query result resource
  294.      * @param array    $arr       the referenced array to put the data in
  295.      * @param int      $fetchmode how the resulting array should be indexed
  296.      * @param int      $rownum    the row number to fetch (0 = first row)
  297.      *
  298.      * @return mixed  DB_OK on success, NULL when the end of a result set is
  299.      *                 reached or on failure
  300.      *
  301.      * @see DB_result::fetchInto()
  302.      */
  303.     function fetchInto($result, &$arr, $fetchmode, $rownum = null)
  304.     {
  305.         if ($rownum === null) {
  306.             $rownum = $this->res_row[(int)$result]++;
  307.         }
  308.         if ($fetchmode & DB_FETCHMODE_ASSOC) {
  309.             $arr = @dbase_get_record_with_names($this->connection, $rownum);
  310.             if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
  311.                 $arr = array_change_key_case($arr, CASE_LOWER);
  312.             }
  313.         } else {
  314.             $arr = @dbase_get_record($this->connection, $rownum);
  315.         }
  316.         if (!$arr) {
  317.             return null;
  318.         }
  319.         if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
  320.             $this->_rtrimArrayValues($arr);
  321.         }
  322.         if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
  323.             $this->_convertNullArrayValuesToEmpty($arr);
  324.         }
  325.         return DB_OK;
  326.     }
  327.  
  328.     // }}}
  329.     // {{{ numCols()
  330.  
  331.     /**
  332.      * Gets the number of columns in a result set
  333.      *
  334.      * This method is not meant to be called directly.  Use
  335.      * DB_result::numCols() instead.  It can't be declared "protected"
  336.      * because DB_result is a separate object.
  337.      *
  338.      * @param resource $result  PHP's query result resource
  339.      *
  340.      * @return int  the number of columns.  A DB_Error object on failure.
  341.      *
  342.      * @see DB_result::numCols()
  343.      */
  344.     function numCols($foo)
  345.     {
  346.         return @dbase_numfields($this->connection);
  347.     }
  348.  
  349.     // }}}
  350.     // {{{ numRows()
  351.  
  352.     /**
  353.      * Gets the number of rows in a result set
  354.      *
  355.      * This method is not meant to be called directly.  Use
  356.      * DB_result::numRows() instead.  It can't be declared "protected"
  357.      * because DB_result is a separate object.
  358.      *
  359.      * @param resource $result  PHP's query result resource
  360.      *
  361.      * @return int  the number of rows.  A DB_Error object on failure.
  362.      *
  363.      * @see DB_result::numRows()
  364.      */
  365.     function numRows($foo)
  366.     {
  367.         return @dbase_numrecords($this->connection);
  368.     }
  369.  
  370.     // }}}
  371.     // {{{ quoteSmart()
  372.  
  373.     /**
  374.      * Formats input so it can be safely used in a query
  375.      *
  376.      * @param mixed $in  the data to be formatted
  377.      *
  378.      * @return mixed  the formatted data.  The format depends on the input's
  379.      *                 PHP type:
  380.      *                 + null = the string <samp>NULL</samp>
  381.      *                 + boolean = <samp>T</samp> if true or
  382.      *                   <samp>F</samp> if false.  Use the <kbd>Logical</kbd>
  383.      *                   data type.
  384.      *                 + integer or double = the unquoted number
  385.      *                 + other (including strings and numeric strings) =
  386.      *                   the data with single quotes escaped by preceeding
  387.      *                   single quotes then the whole string is encapsulated
  388.      *                   between single quotes
  389.      *
  390.      * @see DB_common::quoteSmart()
  391.      * @since Method available since Release 1.6.0
  392.      */
  393.     function quoteSmart($in)
  394.     {
  395.         if (is_int($in) || is_double($in)) {
  396.             return $in;
  397.         } elseif (is_bool($in)) {
  398.             return $in ? 'T' : 'F';
  399.         } elseif (is_null($in)) {
  400.             return 'NULL';
  401.         } else {
  402.             return "'" . $this->escapeSimple($in) . "'";
  403.         }
  404.     }
  405.  
  406.     // }}}
  407.     // {{{ tableInfo()
  408.  
  409.     /**
  410.      * Returns information about the current database
  411.      *
  412.      * @param mixed $result  THIS IS UNUSED IN DBASE.  The current database
  413.      *                       is examined regardless of what is provided here.
  414.      * @param int   $mode    a valid tableInfo mode
  415.      *
  416.      * @return array  an associative array with the information requested.
  417.      *                 A DB_Error object on failure.
  418.      *
  419.      * @see DB_common::tableInfo()
  420.      * @since Method available since Release 1.7.0
  421.      */
  422.     function tableInfo($result = null, $mode = null)
  423.     {
  424.         if (function_exists('dbase_get_header_info')) {
  425.             $id = @dbase_get_header_info($this->connection);
  426.             if (!$id && $php_errormsg) {
  427.                 return $this->raiseError(DB_ERROR,
  428.                                          null, null, null,
  429.                                          $php_errormsg);
  430.             }
  431.         } else {
  432.             /*
  433.              * This segment for PHP 4 is loosely based on code by
  434.              * Hadi Rusiah <deegos@yahoo.com> in the comments on
  435.              * the dBase reference page in the PHP manual.
  436.              */
  437.             $db = @fopen($this->dsn['database'], 'r');
  438.             if (!$db) {
  439.                 return $this->raiseError(DB_ERROR_CONNECT_FAILED,
  440.                                          null, null, null,
  441.                                          $php_errormsg);
  442.             }
  443.  
  444.             $id = array();
  445.             $i  = 0;
  446.  
  447.             $line = fread($db, 32);
  448.             while (!feof($db)) {
  449.                 $line = fread($db, 32);
  450.                 if (substr($line, 0, 1) == chr(13)) {
  451.                     break;
  452.                 } else {
  453.                     $pos = strpos(substr($line, 0, 10), chr(0));
  454.                     $pos = ($pos == 0 ? 10 : $pos);
  455.                     $id[$i] = array(
  456.                         'name'   => substr($line, 0, $pos),
  457.                         'type'   => $this->types[substr($line, 11, 1)],
  458.                         'length' => ord(substr($line, 16, 1)),
  459.                         'precision' => ord(substr($line, 17, 1)),
  460.                     );
  461.                 }
  462.                 $i++;
  463.             }
  464.  
  465.             fclose($db);
  466.         }
  467.  
  468.         if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
  469.             $case_func = 'strtolower';
  470.         } else {
  471.             $case_func = 'strval';
  472.         }
  473.  
  474.         $res   = array();
  475.         $count = count($id);
  476.  
  477.         if ($mode) {
  478.             $res['num_fields'] = $count;
  479.         }
  480.  
  481.         for ($i = 0; $i < $count; $i++) {
  482.             $res[$i] = array(
  483.                 'table' => $this->dsn['database'],
  484.                 'name'  => $case_func($id[$i]['name']),
  485.                 'type'  => $id[$i]['type'],
  486.                 'len'   => $id[$i]['length'],
  487.                 'flags' => ''
  488.             );
  489.             if ($mode & DB_TABLEINFO_ORDER) {
  490.                 $res['order'][$res[$i]['name']] = $i;
  491.             }
  492.             if ($mode & DB_TABLEINFO_ORDERTABLE) {
  493.                 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
  494.             }
  495.         }
  496.  
  497.         return $res;
  498.     }
  499.  
  500.     // }}}
  501. }
  502.  
  503. /*
  504.  * Local variables:
  505.  * tab-width: 4
  506.  * c-basic-offset: 4
  507.  * End:
  508.  */
  509.  
  510. ?>
  511.